﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace XFFSM
{
    /// <summary>
    /// 状态之间的过渡
    /// </summary>
    public class FSMTransition
    {
        #region 字段
        private FSMTransitionData data;
        private RuntimeFSMControllerInstance controller;
        private FSMStateNode toState;

        /// <summary>
        /// 过渡所需的条件
        /// </summary>
        public List<FSMCondition> conditions; 
        #endregion

        #region 属性

        /// <summary>
        /// 过渡数据
        /// </summary>
        public FSMTransitionData Data => data;

        /// <summary>
        /// 过渡目标状态
        /// </summary>
        public FSMStateNode ToState => toState;

        // 条件是否已经满足
        internal bool IsMeet
        {
            get
            {
                // 如果过渡没有条件认为条件满足,可以切换状态
                //if (conditions.Count == 0) return true;

                // 判断是不是所有的条件都满足了 
                foreach (var item in conditions)
                {
                    if (item.state == ConditionState.NotMeet) return false;
                }

                if (toState == null) { Debug.LogError("查询目标状态失败!"); return false; }

                if (!data.fromStateName.Equals(controller.currentState.data.name))
                {

                    // AnyState
                    if (!data.fromStateName.Equals(FSMConst.anyState)) return false;

                    // 判断当前的状态 跟 目标状态是不是一个 
                    if (controller.currentState.data.name.Equals(data.toStateName)) return false;
                }
                return true;
            }

        }

        #endregion

        #region 方法

        internal FSMTransition(RuntimeFSMControllerInstance controller, FSMTransitionData data) {
            this.data = data;
            this.controller = controller;

            this.conditions = new List<FSMCondition>();

            foreach (var item in this.data.conditions)
            {
                FSMCondition condition = new FSMCondition(item, controller);
                condition.onConditionMeet += this.OnConditionMeet;
                this.conditions.Add(condition);
            }

            if ( controller.states.ContainsKey(data.toStateName) ) {
                toState = controller.states[data.toStateName];
            }

        }

        /// <summary>
        /// 当某一个条件满足时不能立即切换状态,需要等待所有的条件状态更新完毕,才能去检测是否要切换状态，
        /// 否则有的条件的状态是旧的，导致状态切换错误的问题
        /// 所以这里延迟一帧调用检测是否满足的方法
        /// </summary>
        private void OnConditionMeet() {
            DelayTools.DelayCall(CheckCondition);
        }

        // 检测条件是否满足
        private void CheckCondition() {
            CheckConditionAndSwitch();
        }

        // 检测条件是不是都满足了
        internal bool CheckConditionAndSwitch() 
        {
            bool isMeet = IsMeet;
            if (isMeet)
            {
                // reset trigger
                ResetTrigger();
                // 切换状态 
                controller.SwitchState(toState,this);
            }
            return isMeet;
        }

        private void ResetTrigger() {
            foreach (var item in conditions)
            {
                if (item.Parameter.parameterType == ParameterType.Trigger)
                    controller.ClearTrigger(item.Parameter.name);
            }
        }

        #endregion

    }

}

